/*
 * Copyright 2016-2019 yoara
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yhao.infra.common.util;

import java.math.BigDecimal;

/**
 * 数学操作工具类
 *
 * @author yoara
 */
public class MathUtil {
	/**
	 * 浮点数转换成整数，四舍五入
	 * 55.51-&gt;56 55.490-&gt;55
	 */
	public static double formatPrice(double price) {
		return Math.round(price);
	}
	/**
	 *
	 * 功能说明：浮点类型四舍五入
	 * @param doubleMath
	 * @param precision 精度
	 */
	public static double rounding(double doubleMath,int precision){
		BigDecimal b = new BigDecimal(doubleMath);
		BigDecimal bigDecimal = b.setScale(precision, BigDecimal.ROUND_HALF_UP);
		return bigDecimal.doubleValue();
	}

	/**
	 *
	 * 功能说明：浮点类型上浮整数
	 * @param doubleMath
	 */
	public static double roundingUp(double doubleMath){
		BigDecimal b = new BigDecimal(doubleMath);
		BigDecimal bigDecimal = b.setScale(0, BigDecimal.ROUND_UP);
		return bigDecimal.doubleValue();
	}
	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
	 *
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的商
	 */
	public static double doubleDiv(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException(
					"The scale must be a positive integer or zero");
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 提供精确的乘法运算。
	 *
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @return 两个参数的积
	 */
	public static double doubleMul(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.multiply(b2).doubleValue();
	}

	/**
	 * 提供精确的乘方运算
	 *
	 * @param v1
	 *            被乘方数
	 * @param v2
	 *            乘方数
	 * @return 乘方结果
	 */
	public static double doublePow(double v1, int v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		return b1.pow(v2).doubleValue();
	}

	/**
	 * 提供精确的减法运算。
	 *
	 * @param v1
	 *            被减数
	 * @param v2
	 *            减数
	 * @return 两个参数的差
	 */
	public static double doubleSubtract(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.subtract(b2).doubleValue();
	}

	/**
	 * 提供精确的加法运算。
	 *
	 * @return 两个参数的和
	 */
	public static double doubleAdd(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.add(b2).doubleValue();
	}

	/**
	 * 提供精确的累加运算。
	 */
	public static double doubleSum(double ... values) {
		double total = 0;
		for(double v:values){
			total = doubleAdd(total,v);
		}
		return total;
	}

	/**浮点数以5为单位向上靠
	 * 50.01-&gt;55，55.00-&gt;60，55.01-&gt;60
	 * @return 上靠的5的倍数
	 */
	public static long doubleToUpperLong(double d1) {
		int L_10 = (int)d1/10;
		int L_1 = 0;
		double D_1  = d1%10;
		if(D_1==0.0){
			L_1 = 0;
		}else if(D_1<5.0){
			L_1 = 5;
		}else if(5.0<=D_1){
			L_1 = 10;
		}
		return L_10*10+L_1;
	}

	/**差值进位算法
	 *@param	start 起始位
	 *@param	end 结束位
	 * start&lt;= x &lt;=end，则x进5
	 * x &lt; start，则x进0
	 * x &gt; end，则x进10
	 * **/
	public static long longToFive(long l1,int start,int end) {
		long t = l1%10;
		if(t>=0){
			if(t<start){
				t = 0;
			}else if(start<=t&&t<=end){
				t = 5;
			}else if(end<t){
				t = 10;
			}
		}else{
			if(t>-start){
				t = 0;
			}else if(-start>=t&&t>=-end){
				t = -5;
			}else if(-end>t){
				t = -10;
			}
		}
		return l1/10*10+t;
	}
}
